package org.example.java8.parallel;

import java.util.function.Function;
import java.util.stream.LongStream;
import java.util.stream.Stream;

public class ParallelProcessing {
    public static void main(String[] args) {
        System.out.println(Runtime.getRuntime().availableProcessors());
        //设置并行数
        System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism","12");

        //System.out.println("the best process time: " + measureSumPerformance(ParallelProcessing::iterateStream, 10_000_000) + " ms,iterateStream");
        //System.out.println("the best process time: " + measureSumPerformance(ParallelProcessing::parallelStream, 10_000_000) + " ms,parallelStream");
        //System.out.println("the best process time: " + measureSumPerformance(ParallelProcessing::parallelStream2, 10_000_000) + " ms,parallelStream2");
        System.out.println("the best process time: " + measureSumPerformance(ParallelProcessing::parallelStream3, 100_000_000) + " ms,parallelStream3");
        System.out.println("the best process time: " + measureSumPerformance(ParallelProcessing::normalAdd, 100_000_000) + " ms,normalAdd");
    }

    private static long measureSumPerformance(Function<Long, Long> adder, long limit) {
        long fastest = Long.MAX_VALUE;
        for (int i = 0; i < 10; i++) {
            long startTimestamp = System.currentTimeMillis();
            long result = adder.apply(limit);
            long duration = System.currentTimeMillis() - startTimestamp;
            //System.out.println("The result of sum: " + result);
            if (duration < fastest) fastest = duration;
        }
        return fastest;
    }

    private static long iterateStream(long limit) {
        return Stream.iterate(1L, i -> i + 1)
                .limit(limit).reduce(0L, Long::sum);
    }

    private static long parallelStream(long limit) {
        return Stream.iterate(1L, i -> i + 1)//拿出来的是object，没次要拆箱，慢
                .parallel()
                .limit(limit).reduce(0L, Long::sum);
    }

    private static long parallelStream2(long limit) {
        return Stream.iterate(1L, i -> i + 1)
                .mapToLong(Long::longValue)
                .parallel()
                .limit(limit).reduce(0L, Long::sum);
    }

    //快
    private static long parallelStream3(long limit) {
        //return LongStream.rangeClosed(1, limit).parallel().sum();
        return LongStream.rangeClosed(1, limit).parallel().reduce(0L, Long::sum);
    }

    //比较快
    private static long normalAdd(long limit) {
        long result = 0L;
        for (long i = 1L; i < limit; i++) {
            result += i;
        }
        return result;
    }


}